package co.fitstart.weapp.api.service.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;

import co.fitstart.entity.coupon.Coupon;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.reference.Country;
import co.fitstart.entity.user.Student;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.UserAccount;
import co.fitstart.entity.user.WechatAccount;
import co.fitstart.entity.user.inbody.InbodyRecord;
import co.fitstart.weapp.api.Constant;
import co.fitstart.weapp.api.dao.CouponDao;
import co.fitstart.weapp.api.dao.CourseRoundDao;
import co.fitstart.weapp.api.dao.InbodyDao;
import co.fitstart.weapp.api.dao.StudentDao;
import co.fitstart.weapp.api.dao.UserDao;
import co.fitstart.weapp.api.service.UserService;

/**
 * 
 * @author dan
 *
 */
@Service("userService")
public class UserServiceImpl implements UserService{
    
    @Dao
    private UserDao userDao;
    
    @Dao
    private StudentDao studentDao;
    
    @Dao
    private CourseRoundDao courseRoundDao;
    
    @Dao
    private InbodyDao inbodyDao;
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;

    @Dao
    private CouponDao couponDao;
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#load(java.lang.String)
     */
    public User load(String unionid) {
        return userDao.load(unionid);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#load(java.lang.Long)
     */
    public User load(Long userId) {
        return genericDaoSupport.load(User.class, userId);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#loadByMobile(java.lang.String)
     */
    public User loadByMobile(String mobile) {
        return userDao.loadByMobile(mobile);
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#editRegion(java.lang.String, java.lang.String, co.fitstart.entity.user.User)
     */
    public void editRegion(String country, String prd, User user) {
        Country countryEnum = Country.privateValueOf(country);
        
        if(country.equalsIgnoreCase("OTHER") && StringUtils.isEmpty(prd)) {
            user.editRegion(countryEnum, null, null, null);
        } else {
            String[] prds = StringUtils.split(prd, ",");
            String provice = prds[0];
            String region= prds.length == 3 ? prds[1] : prds[0];
            String district = prds.length == 3 ? prds[2] : prds[1];
            
            user.editRegion(countryEnum, provice, region, district);
        }
        
        genericDaoSupport.update(user);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#editAddress(java.lang.String, java.lang.String, java.lang.String, java.lang.String, co.fitstart.entity.user.User)
     */
    public void editAddress(String name, String mobile, String region, String address, User user) {
        genericDaoSupport.update(user.editShippingAddress(name, mobile, region, address));
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#latestEffectiveDate(co.fitstart.entity.user.User)
     */
    public Date latestEffectiveDate(User user) {
        return courseRoundDao.getMaxEffectiveDate(user, Arrays.asList(new RoundStatus[]{RoundStatus.PREPARE, RoundStatus.READY, RoundStatus.HOLD, RoundStatus.ACTIVATE, RoundStatus.EXPIRE, RoundStatus.FINISH}));
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#getLatestInbodyRecord(co.fitstart.entity.user.User)
     */
    public InbodyRecord getLatestInbodyRecord(User user) {
        List<InbodyRecord> records = inbodyDao.load(user);
        
        return records.size() > 0 ? records.get(0) : null;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#listInbodyRecord(co.fitstart.entity.user.User)
     */
    public List<InbodyRecord> listInbodyRecord(User user) {
        List<InbodyRecord> records = inbodyDao.list(user);
        return records.size() > 0 ? records : null;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#getStudent(co.fitstart.entity.user.User)
     */
    public Student getStudent(User user) {
        return studentDao.load(user);
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#login(java.lang.String, java.lang.String, java.lang.String, boolean)
     */
    public User login(String mobile, String openid, String unionid, boolean isEmail) {
        List<User> users = userDao.list(unionid);
        for(User user : users) {
            if(!mobile.equals(user.getMobile())) {
                genericDaoSupport.update(user.editUnionid(null));
            }
        }
        
        User user = userDao.loadByMobile(mobile);
        
        if(user == null) {
            user = new User(mobile, isEmail);
            genericDaoSupport.save(user.editUnionid(unionid));
        } else {
            genericDaoSupport.update(user.editUnionid(unionid));
        }
        
        UserAccount openidUserAccount = userDao.loadUserAccount(Constant.USER_ACCOUNT_WEAPP_KEY, openid);
        if(openidUserAccount != null) {
            openidUserAccount.bind(user);
            genericDaoSupport.update(openidUserAccount);
        } else {
            openidUserAccount = new UserAccount(Constant.USER_ACCOUNT_WEAPP_KEY, openid);
            genericDaoSupport.save(openidUserAccount.bind(user));
        }
        
        WechatAccount wechatAccount = userDao.loadWechatAccount(openid, Constant.WECHAT_ACCOUNT_WEAPP_SOURCE);
        if(wechatAccount != null) {
            user.weapp(wechatAccount);
            genericDaoSupport.update(user);
        }
        
        UserAccount mobileUserAccount = userDao.loadUserAccount(Constant.USER_ACCOUNT_MOBILE_KEY, mobile);
        if(mobileUserAccount == null) {
            mobileUserAccount = new UserAccount(Constant.USER_ACCOUNT_MOBILE_KEY, mobile);
            genericDaoSupport.save(mobileUserAccount.bind(user));
        }else {
            genericDaoSupport.update(mobileUserAccount.bind(user));
        }
        
        // if same mobile's inbodyRecords not null, bind user inbody records
        List<InbodyRecord> inbodyRecords = inbodyDao.list(mobile);
        
        if(CollectionUtils.isNotEmpty(inbodyRecords)) {
            for(InbodyRecord inbodyRecord : inbodyRecords) {
                genericDaoSupport.update(inbodyRecord.bindUser(user));
            }
        }
        
        // if same mobile's coupons not null, bind user coupons
        List<Coupon> coupons = couponDao.list(mobile, openid);
        
        if(CollectionUtils.isNotEmpty(coupons)) {
            for(Coupon coupon : coupons) {
                genericDaoSupport.update(coupon.bindUser(user.getId()));
            }
        }
        
        return user;
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#editMobile(co.fitstart.entity.user.User, java.lang.String)
     */
    public void editMobile(User user, String mobile) {
        User mobileUser = userDao.loadByMobile(mobile);
        if(mobileUser != null && !mobileUser.isDisabled()) {
            throw new BusinessException("此手机号已被注册");
        } else {
            UserAccount mobileUserAccount = userDao.loadUserAccount(Constant.USER_ACCOUNT_MOBILE_KEY, user.getMobile());
            if(mobileUserAccount == null) {
                mobileUserAccount = new UserAccount(Constant.USER_ACCOUNT_MOBILE_KEY, mobile);
                genericDaoSupport.save(mobileUserAccount.bind(user));
            }else {
                genericDaoSupport.update(mobileUserAccount.bind(user));
            }
            
            genericDaoSupport.update(user.editMobile(mobile));
            
            Student student = studentDao.load(user);
            if(student != null) {
                genericDaoSupport.update(student.editMobile(mobile));
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.weapp.api.service.UserService#editAvatar(co.fitstart.entity.user.User, java.lang.String, java.lang.String)
     */
    public void editAvatar(User user, String nickname, String avatar) {
        genericDaoSupport.update(user.editAvatar(nickname, avatar));
    }
}
